﻿using System.Net.Sockets;
using Advantech.Adam;
using MagicWatering.Interfaces;

namespace MagicWatering.Scheduler.Controller
{
    /// <summary>
    /// Adam60XX communication adapter.
    /// </summary>
    public class Adam6060Controller: IWateringController
    {
        /// <summary>
        /// MODBUS TCP port is always 502.
        /// </summary>
        private const int s_controllerPort = 502; 
        private readonly AdamSocket m_adamModbus;
        private string m_remoteIpAddress;

        /// <summary>
        /// Constructs communication controller instance. 
        /// </summary>
        /// <param name="ipAddress"></param>
        public Adam6060Controller(string ipAddress)
        {
            m_remoteIpAddress = ipAddress;
            m_adamModbus = new AdamSocket();
            m_adamModbus.SetTimeout(1000, 1000, 1000); 
        }

        #region Implementation of IWateringController

        /// <summary>
        /// Starts communication with remote controller.
        /// </summary>
        /// <returns></returns>
        public bool StartCommunication()
        {
            if (m_adamModbus.Connected)
            {
                return true;
            }
            return m_adamModbus.Connect(m_remoteIpAddress, ProtocolType.Tcp, s_controllerPort);
        }

        /// <summary>
        /// Stops communication with remote controller.
        /// </summary>
        /// <returns></returns>
        public bool StopCommunication()
        {
            if (!m_adamModbus.Connected)
            {
                return true;
            }
            m_adamModbus.Disconnect(); // disconnect slave
            return true;
        }

        /// <summary>
        /// Sets channel state to <c>true</c> or <c>false</c>.
        /// </summary>
        /// <param name="channelId"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool SetChannelState(int channelId, bool value)
        {
            return m_adamModbus.Modbus().ForceSingleCoil(channelId, value);
        }

        /// <summary>
        /// Gets channel state.
        /// </summary>
        /// <param name="channelId"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool GetChannelState(int channelId, out bool value)
        {
            value = false;
            bool[] values;
            bool readStatus =  m_adamModbus.Modbus().ReadCoilStatus(channelId, 1, out values);
            if (!readStatus || null == values || values.Length < 1)
            {
                return false;
            }
            value = values[0];
            return true;
        }

        /// <summary>
        /// Changes IP address of the remote controller.
        /// </summary>
        /// <remarks>Stop communication before to change the IP.</remarks>
        /// <param name="newIpAddress"></param>
        public void ChangeControllerIp(string newIpAddress)
        {
            m_remoteIpAddress = newIpAddress;
        }

        public int LastError
        {
            get { return 0; }
        }

        #endregion
    }
}
